// controllers/purchaseController.js

const Purchase = require("../models/purchaseModel");
const Warehouse = require("../models/warehouseModel");
const Supplier = require("../models/supplierModel");
const PaymentType = require("../models/paymentTypeModel");

// 1) Create a Normal Purchase
exports.createPurchase = async (req, res) => {
  try {
    const { warehouse, supplier, referenceNo, items, purchaseDate, grandTotal } = req.body;

    // Basic validations
    if (
      !warehouse ||
      !supplier ||
      !purchaseDate ||
      !grandTotal ||
      !items ||
      !Array.isArray(items) ||
      items.length === 0
    ) {
      return res
        .status(400)
        .json({ success: false, message: "Missing required fields or items are empty" });
    }
    if (!req.user || !req.user.id) {
      console.error("❌ ERROR: `req.user._id` is missing:", req.user);
      return res.status(400).json({ success: false, message: "User ID not found in request" });
    }

    req.body.createdBy = req.user.id;
    req.body.createdByModel = req.user.role.toLowerCase() === "admin" ? "Admin" : "User";


    console.log("✅ Purchase Data Before Saving:", req.body); 

    // Mark as normal purchase
    req.body.isReturn = false;
    req.body.status = "Normal";

    // Create and save
    const newPurchase = new Purchase(req.body);
    await newPurchase.save();

    return res.status(201).json({
      success: true,
      message: "Purchase created successfully",
      data: newPurchase,
    });
  } catch (error) {
    console.error("Error creating purchase:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 2) Create a Purchase Return or Cancel
exports.createPurchaseReturn = async (req, res) => {
  try {
    const { warehouse, supplier, referenceNo, items, purchaseDate, grandTotal, status } = req.body;

    // Basic validations
    if (
      !warehouse ||
      !supplier ||
      !purchaseDate ||
      !grandTotal ||
      !items ||
      !Array.isArray(items) ||
      items.length === 0
    ) {
      return res
        .status(400)
        .json({ success: false, message: "Missing required fields or items are empty" });
    }

    // Ensure status is "Return" or "Cancel"
    if (!status || !["Return", "Cancel"].includes(status)) {
      return res
        .status(400)
        .json({ success: false, message: "Status must be 'Return' or 'Cancel'" });
    }
    if (!req.user || !req.user.id) {
      console.error("❌ ERROR: req.user._id is missing:", req.user);
      return res.status(400).json({ success: false, message: "User ID not found in request" });
    }
    
    req.body.createdBy = req.user.id;
    req.body.createdByModel = req.user.role.toLowerCase() === "admin" ? "Admin" : "User";

    
    console.log("✅ Purchase Data Before Saving:", req.body); 

    // Mark as return
    req.body.isReturn = true;
    req.body.status = status;

    // Check if there's an original purchase to reference
    const originalPurchase = await Purchase.findOne({
      referenceNo,
      supplier,
      warehouse,
      isReturn: false,
      status: "Normal",
    });
    if (!originalPurchase) {
      return res
        .status(400)
        .json({ success: false, message: "No valid purchase found to return items" });
    }

    // Create and save
    const newPurchaseReturn = new Purchase(req.body);
    await newPurchaseReturn.save();

    return res.status(201).json({
      success: true,
      message:
        status === "Return"
          ? "Purchase Return created successfully"
          : "Purchase cancellation recorded successfully",
      data: newPurchaseReturn,
    });
  } catch (error) {
    console.error("Error creating purchase return:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 3) Get All Normal Purchases (with Summary)
exports.getAllPurchases = async (req, res) => {
  try {
    // A) Aggregation for summary
    // 1. Count how many normal purchases exist
    const totalInvoices = await Purchase.countDocuments({ isReturn: false });

    // 2. Sum up grandTotal for all normal purchases
    const invoiceAmountAgg = await Purchase.aggregate([
      { $match: { isReturn: false } },
      { $group: { _id: null, total: { $sum: "$grandTotal" } } },
    ]);
    const totalInvoiceAmount = invoiceAmountAgg.length ? invoiceAmountAgg[0].total : 0;

    // 3. Sum all payments for normal purchases
    const paymentsAgg = await Purchase.aggregate([
      { $match: { isReturn: false } },
      { $unwind: "$payments" },
      { $group: { _id: null, total: { $sum: "$payments.amount" } } },
    ]);
    const totalPaidAmount = paymentsAgg.length ? paymentsAgg[0].total : 0;

    // 4. Total purchase due
    const totalPurchaseDue = totalInvoiceAmount - totalPaidAmount;

    // B) Fetch the list of normal purchases
    const purchases = await Purchase.find({ isReturn: false })
      .populate("warehouse", "warehouseName")
      .populate("supplier", "name email")
      .populate("items.item", "itemName salesPrice")
      .populate("payments.paymentType", "paymentTypeName")
      .populate("createdBy"); // Explicit fields

    // Process each purchase to add a computed 'creatorName' field
    const processedPurchases = purchases.map((purchase) => {
      let creatorName = "";
      if (purchase.createdBy) {
        if (purchase.createdByModel === "Admin" && purchase.createdBy.name) {
          creatorName = purchase.createdBy.name;
        } else if (purchase.createdBy.FirstName && purchase.createdBy.LastName) {
          creatorName = `${purchase.createdBy.FirstName} ${purchase.createdBy.LastName}`;
        }
      }
      return {
        ...purchase.toObject(),
        creatorName,
      };
    });

    // C) Return summary + list using processedPurchases
    return res.status(200).json({
      success: true,
      summary: {
        totalInvoices,
        totalInvoiceAmount,
        totalPaidAmount,
        totalPurchaseDue,
      },
      data: processedPurchases,
    });
  } catch (error) {
    console.error("Error fetching purchases:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 4) Get All Purchase Returns (with Summary)
exports.getAllPurchaseReturns = async (req, res) => {
  try {
    // A) Aggregation for summary
    // 1. Count how many return invoices exist
    const totalReturnInvoices = await Purchase.countDocuments({ isReturn: true });

    // 2. Sum up grandTotal for all returns
    const returnAmountAgg = await Purchase.aggregate([
      { $match: { isReturn: true } },
      { $group: { _id: null, total: { $sum: "$grandTotal" } } },
    ]);
    const totalReturnInvoiceAmount = returnAmountAgg.length ? returnAmountAgg[0].total : 0;

    // 3. Sum all payments for return purchases
    const paymentsAgg = await Purchase.aggregate([
      { $match: { isReturn: true } },
      { $unwind: "$payments" },
      { $group: { _id: null, total: { $sum: "$payments.amount" } } },
    ]);
    const totalReturnPaidAmount = paymentsAgg.length ? paymentsAgg[0].total : 0;

    // 4. Total purchase return due
    const totalReturnDue = totalReturnInvoiceAmount - totalReturnPaidAmount;

    // B) Fetch the list of return purchases
    const returns = await Purchase.find({ isReturn: true })
      .populate("warehouse", "warehouseName")
      .populate("supplier", "name email")
      .populate("items.item", "itemName salesPrice")
      .populate("payments.paymentType", "paymentTypeName")
      .populate("createdBy"); // populate full document

    // Process each purchase to add a computed 'creatorName' field
    const processedReturns = returns.map(purchase => {
      let creatorName = "";
      if (purchase.createdBy) {
        if (purchase.createdByModel === "Admin" && purchase.createdBy.name) {
          creatorName = purchase.createdBy.name;
        } else if (purchase.createdBy.FirstName && purchase.createdBy.LastName) {
          creatorName = `${purchase.createdBy.FirstName} ${purchase.createdBy.LastName}`;
        }
      }
      return {
        ...purchase.toObject(),
        creatorName,
      };
    });

    // C) Return summary + list using processedReturns
    return res.status(200).json({
      success: true,
      summary: {
        totalReturnInvoices,
        totalReturnInvoiceAmount,
        totalReturnPaidAmount,
        totalReturnDue,
      },
      data: processedReturns,
    });
  } catch (error) {
    console.error("Error fetching purchase returns:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 5) Get a Single Purchase by ID
exports.getPurchaseById = async (req, res) => {
  try {
    const purchase = await Purchase.findById(req.params.id)
      .populate("warehouse", "warehouseName")
      .populate("supplier", "name email")
      .populate("items.item", "itemName salesPrice")
      .populate("payments.paymentType", "paymentTypeName")
      .populate("createdBy"); // populate full document

    if (!purchase) {
      return res.status(404).json({ success: false, message: "Purchase not found" });
    }

    // Compute creatorName directly for the single purchase
    let creatorName = "";
    if (purchase.createdBy) {
      if (purchase.createdByModel === "Admin" && purchase.createdBy.name) {
        creatorName = purchase.createdBy.name;
      } else if (purchase.createdBy.FirstName && purchase.createdBy.LastName) {
        creatorName = `${purchase.createdBy.FirstName} ${purchase.createdBy.LastName}`;
      }
    }

    const processedPurchase = { ...purchase.toObject(), creatorName };

    return res.status(200).json({ success: true, data: processedPurchase });
  } catch (error) {
    console.error("Error fetching purchase:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 6) Update a Purchase
exports.updatePurchase = async (req, res) => {
  try {
    const updatedPurchase = await Purchase.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
    });

    if (!updatedPurchase) {
      return res.status(404).json({ success: false, message: "Purchase not found" });
    }
    return res.status(200).json({
      success: true,
      message: "Purchase updated successfully",
      data: updatedPurchase,
    });
  } catch (error) {
    console.error("Error updating purchase:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

// 7) Delete a Purchase
exports.deletePurchase = async (req, res) => {
  try {
    const deletedPurchase = await Purchase.findByIdAndDelete(req.params.id);
    if (!deletedPurchase) {
      return res.status(404).json({ success: false, message: "Purchase not found" });
    }
    return res
      .status(200)
      .json({ success: true, message: "Purchase deleted successfully" });
  } catch (error) {
    console.error("Error deleting purchase:", error);
    return res.status(500).json({ success: false, message: error.message });
  }
};
